﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using Kotonoha.Server.Db.Dao;
using Kotonoha.Server.Objects.Model;
using Kotonoha.Server.Core.Utils;
using Kotonoha.Server.Dictionaries;
using Kotonoha.Server.Model;
using Kotonoha.Server.Plugins;
using Kotonoha.Server.UI.Model;
using Kotonoha.Server.UI.Resolver;
using Kotonoha.Server.UI.Settings;
using Kotonoha.Server.UI.Synch;
using Microsoft.Win32;
using Microsoft.Windows.Controls;
using NHibernate;

namespace Kotonoha.Server.UI {
    /// <summary>
    /// Interaction logic for KotonohaMain.xaml
    /// </summary>
    public partial class KotonohaMain : Window {
        private ObservableCollection<Word> words;
        private WordFiller filler;
        private ListCollectionView view;

        public KotonohaMain() {
            InitializeComponent();
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e) {
            SettingsForm form = new SettingsForm();
            form.Show();
        }

        private void KotonohaMain_OnInitialized(object sender, EventArgs e) {
            PluginManager manager = PluginManager.Instance;
            manager.Load(new DirectoryInfo("./Plugins"));
            /*if (!ResourceManager.Instance.Configure()) {
                SettingsForm form = new SettingsForm();
                form.ShowDialog();
                if (!ResourceManager.Instance.Configure()) {
                    Application.Current.Shutdown(1);
                }
            }*/

            filler = new WordFiller();
            refreshList();
        }

        private void refreshList() {
            IQuery q = HibernateUtil.Model.Session.CreateQuery("from Word w join fetch w.Repetition join fetch w.Translations group by w.id");
            words = new ObservableCollection<Word>(q.List<Word>());
            view = (ListCollectionView) CollectionViewSource.GetDefaultView(words);
            wordList.ItemsSource = view;
        }

        private void AddWord_Click(object sender, RoutedEventArgs e) {
            string s = SearchBox.Text;
            if (!string.IsNullOrEmpty(s)) {
                IList<WordEntry> found = new DictDao(HibernateUtil.Dictionary.Session).findWordByWriting(s);
                IList<WordEntry> resolved;
                if (found.Count == 0) {
                    Word w = new Word();
                    w.Translations.Add("");
                    w.Writing = s;
                    WordForm form = new WordForm();
                    form.DataContext = w;
                    if (form.ShowDialog() ?? false) {
                        WordFiller.fillCommonInWord(w);
                        addWord(w);
                    }
                }
                if (found.Count > 1) {
                    WordResolver resolver = new WordResolver();
                    resolver.DataContext = found;
                    resolver.ShowDialog();
                    resolved = resolver.ResolvedWords;
                } else {
                    resolved = found;
                }
                foreach (var entry in resolved) {
                    Word w;
                    if (filler.fill(entry, s, out w)) {
                        addWord(w);
                    }
                }
            }
        }

        private void addWord(Word w) {
            if (words.IndexOf(w) == -1) {
                words.Add(w);
                ISession session = HibernateUtil.Model.Session;
                ITransaction transaction = session.BeginTransaction();
                try {
                    session.Save(w);
                    foreach (string s in KanjiFactory.enumerateKanji(w.Writing)) {
                        if (!new ModelDao(HibernateUtil.Model.Session).existKanji(s)) {
                            Kanji kanji = KanjiFactory.create(s);
                            session.Save(kanji);
                        }
                    }
                    transaction.Commit();
                } catch {
                    transaction.Rollback();
                    throw;
                }
            }
        }

        private void KotonohaMain_Closed(object sender, EventArgs e) {}

        private void SynchItem_Click(object sender, RoutedEventArgs e) {
            SynchForm form = new SynchForm();
            form.ShowDialog();
            refreshList();
        }

        private void ImportItem_Click(object sender, RoutedEventArgs e) {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "CSV files|*.csv";
            bool? result = dialog.ShowDialog(this);
            if (result ?? false) {
                CSVReader reader = new CSVReader(File.OpenRead(dialog.FileName), Encoding.UTF8);
                ISession session = HibernateUtil.Model.Session;
                ModelDao dao = new ModelDao(session);
                ITransaction transaction = session.BeginTransaction();
                try {
                    foreach (Word w in reader) {
                        if (words.IndexOf(w) == -1) {
                            words.Add(w);
                            session.Save(w);
                            foreach (string s in KanjiFactory.enumerateKanji(w.Writing)) {
                                if (!dao.existKanji(s)) {
                                    Kanji kanji = KanjiFactory.create(s);
                                    session.Save(kanji);
                                }
                            }
                        }
                    }
                    transaction.Commit();
                } catch {
                    transaction.Rollback();
                    throw;
                }
            }
        }

        private void DeleteWord_Click(object sender, RoutedEventArgs e) {
            IList items = wordList.SelectedItems;

            ISession s = HibernateUtil.Model.Session;
            ITransaction tran = s.BeginTransaction();
            try {
                foreach (var o in items) {
                    Word w = (Word) o;
                    s.Delete(w);
                }
                tran.Commit();
                //Need to create intermediate collection, otherwise there is a modification of selected items collection.
                items.Cast<Word>().ToList().ForEach(w => words.Remove(w));
            } catch (Exception) {
                tran.Rollback();
                throw;
            }
        }

        private void WordList_OnSorting(object sender, DataGridSortingEventArgs e) {
        }

        private void SearchBox_KeyDown(object sender, KeyEventArgs e) {
            if (e.Key == Key.Return) {
                AddWord_Click(sender, e);
                SearchBox.SelectionStart = 0;
                SearchBox.SelectionLength = SearchBox.Text.Length;
            }
        }

        private void WordList_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) {
            WordForm form = new WordForm();
            object o = wordList.SelectedItem;
            form.DataContext = o;
            bool? dialog = form.ShowDialog();
            bool val = dialog ?? false;
            ISession s = HibernateUtil.Model.Session;
            if (val) {
                ITransaction t = s.BeginTransaction();
                try {
                    s.Update(o);
                    t.Commit();
                } catch {
                    t.Rollback();
                    throw;
                }
            } else {
                s.Refresh(o);
            }
        }

        private void SearchBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) {
            wordList.Items.Filter = delegate(object o) {
                                        var w = (Word) o;
                                        string value = SearchBox.Text;
                                        return w.Reading.StartsWith(value) || w.Writing.StartsWith(value);
                                    };
        }
    }
}